import { BaseDirectory, create, mkdir, remove } from '@tauri-apps/plugin-fs';
import { uniqBy } from 'lodash';
import { useCallback, useEffect, useRef } from 'react';
import { onFilesUpdate, onImageUpdate, onTextUpdate, startListening } from 'tauri-plugin-clipboard-api';
import { previewCache } from './caches';
import useStorageState from './useStorageState';

async function hashString(str) {
  const encoder = new TextEncoder();
  const data = encoder.encode(str); // 转为Uint8Array
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
}

async function getImageInfo(base64, maxWidth = 512) {
  return new Promise((resolve) => {
    const img = new Image();
    img.src = 'data:image/jpeg;base64,' + base64; // 确保是 Base64 格式
    img.onload = () => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const result = {};

      // 小于最大宽度则直接返回原图
      if (img.width <= maxWidth) {
        result.preview = 'data:image/jpeg;base64,' + base64; // 保持原图 Base64
      } else {
        // 计算缩放后的尺寸（保持宽高比）
        let width = img.width;
        let height = img.height;
        if (width > maxWidth) {
          height = Math.floor((height * maxWidth) / width);
          width = maxWidth;
        }

        // 设置 Canvas 尺寸并绘制
        canvas.width = width;
        canvas.height = height;
        ctx.drawImage(img, 0, 0, width, height);
        // 转换为 Base64（可调整压缩质量）
        const compressedBase64 = canvas.toDataURL('image/jpeg', 1); // 质量（0-1）
        result.preview = compressedBase64;
      }
      // kb | M
      result.size = Math.round((base64.length * 3) / 4 / 1024); // Base64 编码后长度除以 4 再乘以 3 得到图片大小（单位：kb）
      if (result.size > 1024) {
        result.size = (result.size / 1024).toFixed(2) + 'M'; // 转换为 MB
      } else {
        result.size = result.size + 'kb'; // 保留 kb 单位
      }
      result.width = img.width;
      result.height = img.height;
      resolve(result);
    };
  });
}

export function useClipboardListener() {
  const [items, setItems] = useStorageState('clipboard-items', []);
  const hasListenRef = useRef(false);
  const handleTextChangeRef = useRef(null);
  const handleImageChangeRef = useRef(null);
  const handleFilesChangeRef = useRef(null);
  const pushItem = useCallback((item) => {
    setItems((prev) => {
      return uniqBy([item, ...prev], 'hash');
    });
  }, []);
  handleTextChangeRef.current = useCallback(async (text) => {
    const hash = await hashString(text);
    const item = { type: 'text', length: text.length, hash };
    item.timestamp = Date.now();
    mkdir('data', { baseDir: BaseDirectory.AppCache, recursive: true });
    const preview = await create(`data/${hash}.preview`, { baseDir: BaseDirectory.AppCache });
    await preview.write(new TextEncoder().encode(text.slice(0, 500)));
    await preview.close();
    const content = await create(`data/${hash}.content`, { baseDir: BaseDirectory.AppCache });
    await content.write(new TextEncoder().encode(text));
    await content.close();
    pushItem(item);
  }, []);

  handleImageChangeRef.current = useCallback(async (image) => {
    const hash = await hashString(image);
    const item = { type: 'image', hash, timestamp: Date.now() };
    const imgInfo = await getImageInfo(image);
    item.size = imgInfo.size;
    item.width = imgInfo.width;
    item.height = imgInfo.height;
    mkdir('data', { baseDir: BaseDirectory.AppCache, recursive: true });
    const preview = await create(`data/${hash}.preview`, { baseDir: BaseDirectory.AppCache });
    await preview.write(new TextEncoder().encode(imgInfo.preview));
    await preview.close();
    const content = await create(`data/${hash}.content`, { baseDir: BaseDirectory.AppCache });
    await content.write(new TextEncoder().encode(image));
    await content.close();
    pushItem(item);
  }, []);

  handleFilesChangeRef.current = useCallback((files) => {
    console.log('Files updated', files);
  }, []);

  const handleRemoveItem = useCallback(
    (item) => {
      if (!item?.hash) {
        return;
      }
      setItems((prev) => prev.filter((i) => i.hash !== item.hash));
      // 删除文件
      remove(`data/${item.hash}.content`, { baseDir: BaseDirectory.AppCache });
      remove(`data/${item.hash}.preview`, { baseDir: BaseDirectory.AppCache });
      // 删除缓存
      delete previewCache[item.hash]
    },
    [setItems]
  );

  useEffect(() => {
    if (hasListenRef.current) {
      return;
    }
    hasListenRef.current = true;
    onImageUpdate((image) => handleImageChangeRef.current(image));
    onTextUpdate((text) => handleTextChangeRef.current(text));
    onFilesUpdate((files) => handleFilesChangeRef.current(files));
    startListening();
  }, []);

  // 设置上限
  useEffect(() => {
    const maxCount = 500;
    if(items?.length > maxCount){
      let i = maxCount;
      while(i < items.length){
        handleRemoveItem(items[i]);
        i++;
      }
    }
  }, [items]);

  return [items, { removeItem: handleRemoveItem }];
}
